<?php
/**
 * FUserModel.class.php
 * 前台用户模型(FrontUser)
 *
 * @author 王中艺 <[email address]>
 * @date   2017-02-10
 */

namespace Admin\Model;

class FUserModel extends BaseModel{

    //名称映射
    const ROLE_MAP  = [
        101 => '健康合伙人', 
        102 => '健康教练A', 
        103 => '健康教练B', 
        104 => '健康教练C', 
        105 => '健康推广大使', 
        106 => '健康家长'
    ];
    const SEX_MAP   = [
        1   => '男',
        2   => '女'
    ];

    //重定义数据表
    protected $trueTableName = 't_user';

    /**
     * 获取用户列表
     * @param   $keyword    关键词
     * @param   $roleId     角色ID
     * @param   $sort   排序
     * @param   $desc   是否倒序
     * @param   $page   页码数
     * @param   $timeS  开始时间
     * @param   $timeE  结束时间
     * @param   $fatherId   父ID
     * @param   &$pageHtml  页码HTML
     * @param   &$count     用户数量
     * @return  $list
     */
    function getList($keyword, $roleId, $sort, $desc, $page, $timeS, $timeE, $fatherId, &$pageHtml, &$count){
        $where  = '1 = 1';
        if($fatherId){
            $modal  = M('t_user_relative a', null)
                ->join('left join t_user b on a.user_id = b.id')
                ->join('left join t_user_sole_info c on a.user_id = c.user_id');

            $fatherInfo     = $this->getUserInfo($fatherId);
            if($fatherInfo['role_id'] == 101){
                $where  .= ' and a.dean_id = '.$fatherId.' and a.expand_id <= 0 and a.teacher_id <= 0 and a.parent_id <= 0';
            }else if($fatherInfo['role_id'] >= 102 && $fatherInfo['role_id'] <= 104){
                $where  .= ' and a.expand_id = '.$fatherId.' and teacher_id <= 0 and parent_id <= 0';
            }else if($fatherInfo['role_id'] == 105){
                $where  .= ' and a.teacher_id = '.$fatherId.' and parent_id <= 0';
            }else{
                $where  .= ' and a.parent_id = '.$fatherId;
            }
        }else{
            $modal  = $this->table('t_user b')
                ->join('left join t_user_sole_info c on b.id = c.user_id');
        }

        if($roleId && in_array($roleId, array(101, 102, 103, 104, 105, 106))){
            $where  .= ' and role_id = '.$roleId;
        }
        if($keyword){
            $where  .= sprintf(' and (id = %s or nickname like "%%%s%%" or truename like "%%%s%%" or username like "%%%s%%")', (int)$keyword, $keyword, $keyword, $keyword);
        }
        if($timeS){
            $where  .= sprintf(' and subscribe_time >= %d', $timeS);
        }
        if($timeE){
            $where  .= sprintf(' and subscribe_time <= %d', $timeE);
        }
        
        if($sort && in_array($sort, [
            'amount', 'wallet', 'develop_count', 'score', 'role_id', 
            'vip_level', 'child_school', 'child_course_name'
        ])){
            //中文排序处理
            if(in_array($sort, ['child_school', 'child_course_name'])){
                $sort   = sprintf('convert(`%s` using gb2312)', $sort);
            }
            //倒叙处理
            if($desc){
                $sort   = $sort.' desc';
            }
        }else{
            $sort   = 'id';
        }
        
        $list   = $modal->where($where)->order($sort)->page($page, C('PAGE_COUNT'))->select();
        $list   = $this->_analyField('frontuser', $list, true);
        $list   = $this->getChildCount($list, true);

        if($fatherId){
            $modal  = M('t_user_relative a', null)
                ->join('left join t_user b on a.user_id = b.id')
                ->join('left join t_user_sole_info c on a.user_id = c.user_id');
        }else{
            $modal  = $this->table('t_user b')
                ->join('left join t_user_sole_info c on b.id = c.user_id');
        }
        $count  = $modal->where($where)->count();
        $Page   = new \Think\Page($count, C('PAGE_COUNT'));
        $pageHtml   = $Page->angular_show();

        return $list;
    }

    /**
     * 获取用户下线人数
     * @param   $info
     * @param   $isBatch
     * @return  $info
     */
    function getChildCount($info, $isBatch = false){
        if($isBatch){
            $list   = $info;
            foreach($list as $item){
                //下线人数计算
                if($item['role_id'] == 101){
                    $deanIds[]  = $item['id'];
                }else if(in_array($item['role_id'], [102, 103, 104])){
                    $expandIds[]    = $item['id'];
                }else if($item['role_id'] == 105){
                    $teacherIds[]   = $item['id'];
                }else{
                    $parentIds[]    = $item['id'];
                }
            }
            $childCountInfo = [];
            if(isset($deanIds)){
                $childCountInfo     += (array)M('t_user_relative', null)
                    ->where('dean_id in (%s)', implode(',', $deanIds))
                    ->group('dean_id')
                    ->getField('dean_id as user_id, count(user_id) as count');
            }
            if(isset($expandIds)){
                $childCountInfo     += (array)M('t_user_relative', null)
                    ->where('expand_id in (%s)', implode(',', $expandIds))
                    ->group('expand_id')
                    ->getField('expand_id as user_id, count(user_id) as count');
            }
            if(isset($teacherIds)){
                $childCountInfo     = (array)M('t_user_relative', null)
                    ->where('teacher_id in (%s)', implode(',', $teacherIds))
                    ->group('teacher_id')
                    ->getField('teacher_id as user_id, count(user_id) as count');
            }
            if(isset($parentIds)){
                $childCountInfo     += (array)M('t_user_relative', null)
                    ->where('parent_id in (%s)', implode(',', $parentIds))
                    ->group('parent_id')
                    ->getField('parent_id as user_id, count(user_id) as count');
            }
            
            foreach($list as &$item){
                $item['child_count']    = $childCountInfo[$item['id']] ? $childCountInfo[$item['id']] : 0;
            }

            return $list;
        }
    }

    /**
     * 获取VIP用户列表
     * @param   $keyword    关键词
     * @param   $sort   
     * @param   $desc   
     * @param   $page   页码数
     * @param   &$pageHtml  页码HTML
     * @return  $list   用户列表
     */
    function getVipList($keyword, $sort, $desc, $page, &$pageHtml){
        $where  = 'vip_level > 0 and vip_endtime > '.time();
        if($keyword !== false){
            $where  .= sprintf(' and (nickname like "%%%s%%" or truename like "%%%s%%" or username like "%%%s%%" or id = "%s")', $keyword, $keyword, $keyword, $keyword);
        }
        
        if(in_array($sort, ['vip_level', 'vip_endtime', 'child_school', 'child_course_name'])){
            //中文字段排序处理
            if(in_array($sort, ['child_school', 'child_course_name'])){
                $sort   = sprintf('convert(`%s` using gb2312)', $sort); 
            }
            //倒序处理
            if($desc){
                $sort   .= ' desc';
            }
        }else{
            $sort   = 'id';
        }
        $list   = $this->where($where)
            ->page($page, C('PAGE_COUNT'))
            ->order($sort)
            ->select();

        $list   = $this->_analyField('frontuser', $list, true);

        if($pageHtml === true){
            $count  = $this->where('vip_level > 0')->count();
            $Page   = new \Think\Page($count, C('PAGE_COUNT'));
            $pageHtml   = $Page->angular_show();
        }

        return $list;
    }

    /**
     * 获取用户详情信息
     * @param   $userId 用户ID
     * @return  $userInfo
     */
    function getUserInfo($userId){
        $cacheKey   = 'user_info_'.$userId;
        $userInfo   = S($cacheKey);
        if(!$userInfo){
            $userInfo   = $this->table('t_user a')
                ->join('left join t_user_sole_info b on a.id = b.user_id')
                ->where('a.id = %d', $userId)
                ->find();

            $userInfo   = $this->_analyField('frontuser', $userInfo, false);
            S($cacheKey, $userInfo);
        }
        
        return $userInfo;
    }

    /**
     * 获取用户关系连信息
     * @param   $userId 用户ID
     * @return  $relaInfo
     */
    function getRelaInfo($userId){
        $cacheKey   = 'user_rela_info_'.$userId;
        $relaInfo   = S($cacheKey);
        if(!$relaInfo){
            $relaInfo   = M('t_user_relative', null)
                ->where('user_id = %d', $userId)
                ->find();
            //计算上级ID
            foreach($relaInfo as $key=>$val){
                if($key == 'user_id')   continue;
                if($val > 0)    $fatherId   = $val;
            }
            $fatherId   = $fatherId ? $fatherId : 0;
            foreach($relaInfo as $key=>$val){
                if($key == 'user_id')   unset($relaInfo[$key]);
                if($val > 0)    $userIds[]  = $val;
            }
            $userIds[]  = $userId;
            $userIds    = implode(',', $userIds);
            $users  = $this->where('id in (%s)', $userIds)->getField('id, nickname, role_id');
            foreach($relaInfo as $key=>&$val){
                if($val == -1)  continue;
                if($val == 0)   $val    = $userId;

                $val    = $users[$val];
            }
            $relaInfo['father_id']  = $fatherId;

            S($cacheKey, $relaInfo);
        }
            
        return $relaInfo;
    }

    /**
     * 获取指定用户下级用户
     * @param   $userId 指定用户
     * @param   $roleId 制定下级角色
     * @param string $keyword 关键词
     * @param string $sort 排序字段
     * @param int $desc 是否倒序
     * @param int $page 页码数
     * @param string $pageHtml 页面页数html
     * @return  $list
     */
    function getChildUsers($userId, $roleId, $keyword, $sort, $desc, $page, &$pageHtml){
        $userInfo   = $this->getUserInfo($userId);
        if($userInfo['role_id'] == 101){
            $where  = 'a.dean_id='.$userId.' and expand_id <= 0 and teacher_id <= 0 and parent_id <= 0';
        }else if($userInfo['role_id'] >= 102 && $userInfo['role_id'] <= 104){
            $where  = 'a.expand_id = '.$userId.' and teacher_id <= 0 and parent_id <= 0';
        }else if($userInfo['role_id'] == 105){
            $where  = 'a.teacher_id = '.$userId.' and parent_id <= 0';
        }else{
            $where  = 'a.parent_id = '.$userId;
        }

        if($roleId && in_array($roleId, array(101, 102, 103, 104, 105, 106))){
            $where  .= ' and b.role_id = '.$roleId;
        }
        if($keyword){
            $where  .= ' and b.nickname like "%'.$keyword.'%"';
        }
        if($sort && in_array($sort, array('amount', 'wallet', 'develop_count', 'score'))){
            $sort   = 'b.'.$sort;
            if($desc)   $sort   .= ' desc';
        }else{
            $sort   = 'b.id';
        }

        $list   = M('t_user_relative a', null)
            ->join('left join t_user b on a.user_id = b.id')
            ->where($where)
            ->order($sort)
            ->page($page, C('PAGE_COUNT'))
            ->select();
            
        foreach($list as &$val){
            $val['sex_text']    = self::SEX_MAP[$val['sex']];
            $val['role_text']   = self::ROLE_MAP[$val['role_id']];
        }

        $count  = M('t_user_relative a', null)
            ->join('left join t_user b on a.user_id = b.id')
            ->where($where)
            ->count();
        $Page   = new \Think\Page($count, C('PAGE_COUNT'));
        $pageHtml   = $Page->angular_show();

        return $list;
    }

    /**
     * 更改用户信息
     * @param int $userId 用户ID
     * @param array $userInfo 用户信息
     * @return boolean 是否成功
     */
    function changeUserInfo($userId, $userInfo){
        write_log('./Log/run.log', 'UserInfo', $userInfo);
        $result     = $this->where('id = %d', $userId)->save($userInfo);
        //销毁缓存
        S('user_info_'.$userId, null);

        if($result === false){
            $this->errMsg   = '数据变更失败!';
            return false;
        }

        return true;
    }

    /**
     * 更改用户关系链
     * @param   $userId 用户ID
     * @param int $fatherId 上级ID
     * @return boolean [description]
     */
    function changeRelaInfo($userId, $fatherId){
        $userInfo   = $this->getUserInfo($userId);
        $fatherInfo     = $this->getUserInfo($fatherId);

        //检测角色层级关系
        if($userInfo['role_id'] <= $fatherInfo['role_id']){
            $this->errMsg   = '上级用户角色等级不高于当前角色!';
            return false;
        }

        $relaInfos  = M('t_user_relative', null)
            ->where('user_id in (%d, %d)', $userId, $fatherId)
            ->getField('user_id, dean_id, expand_id, teacher_id, parent_id');

        foreach($relaInfos as &$relaInfo){
            unset($relaInfo['user_id']);
        }
        $userRelaInfo   = $relaInfos[$userId];
        $fatherRelaInfo     = $relaInfos[$fatherId];

        $fRoleField     = $this->getRoleField($fatherInfo['role_id']);
        foreach($fatherRelaInfo as $key => $val){
            if($val == 0 || $key == $fRoleField)
                $val    = $fatherId;
            $changeField[$key]  = $val;
            if($key == $fRoleField)
                break;
        }
        //根据当前用户角色查找子用户
        $uRoleField     = $this->getRoleField($userInfo['role_id']);
        //修改子用户角色
        $result     = M('t_user_relative', null)
            ->where('%s = %d', $uRoleField, $userId)
            ->save($changeField);

        //修改当前用户并将角色改为直属
        $changeField    = (array)$changeField + ['dean_id' => -1, 'expand_id' => -1, 'teacher_id' => -1, 'parent_id' => -1];
        $changeField[$uRoleField]   = 0;
        $result     = M('t_user_relative' ,null)
            ->where('user_id = %d', $userId)
            ->save($changeField);

        if($result === false){
            $this->errMsg   = '关系连信息保存失败!';
            return false;
        }

        //消息通知
        $wxTempMsg  = \Wechat\Util\WxTempMsg::getInstance();
        $wxTempMsg->changeFather($userInfo, $fatherInfo);
        $wxTempMsg->addChild($fatherInfo, $userInfo);

        //销毁缓存
        S('user_rela_info_'.$userId, null);
        
        return true;
    }

    /**
     * 获取用户角色字段
     * @param   $roleId
     * @return  $roleField
     */
    function getRoleField($roleId){
        if($roleId == 101)
            return 'dean_id';
        if($roleId >= 102 && $roleId <= 104)
            return 'expand_id';
        if($roleId  == 105)
            return 'teacher_id';

        return 'parent_id';
    }

    /**
     * 获取导出EXCEL数据
     * @param   $timeS 开始时间
     * @param   $timeE 结束时间
     * @param   $fatherId
     * @param   $keyword 上级ID
     * @param   $sort   排序字段
     * @param   $desc 是否倒序
     * @param   $count 数据量
     */
    function getExcelList($timeS, $timeE, $fatherId, $keyword, $start, $length, $sort, $desc, &$count){
        $list   = array();
        $sort   = $sort ? $sort : 'role_id';
        $sort   = $desc ? $sort.' desc' : $sort;

        //导入指定用户下级
        if($fatherId){
            $fatherInfo     = $this->getUserInfo($fatherId);
            if($fatherInfo['role_id'] == 101){
                $where  = 'a.dean_id='.$fatherId.' and a.expand_id<=0 and a.teacher_id<=0 and a.parent_id<=0';
            }else if($fatherInfo['role_id'] >= 102 and $fatherInfo['role_id'] <= 104){
                $where  = 'a.expand_id='.$fatherId.' and a.teacher_id<=0 and a.parent_id<=0';
            }else if($fatherId == 105){
                $where  = 'a.teacher_id='.$fatherId.' and a.parent_id<=0';
            }else{
                $where  = 'a.parent_id='.$fatherId;
            }
            $where  = $where.' and '.$this->createWhere($keyword, 'b');
            if($timeS){
                $where  .= ' and b.subscribe_time > '.$timeS;
            }
            if($timeE){
                $where  .= ' and b.subscribe_time < '.$timeE;
            }

            if($count !== 'only'){
                $list   = M('t_user_relative a', null)
                    ->join('left join t_user b on a.user_id = b.id')
                    ->join('left join t_user_sole_info c on a.user_id = c.user_id')
                    ->where($where)
                    ->order('b.'.$sort)
                    ->limit($start, $length)
                    ->field('b.id, b.nickname, b.truename, b.mobile, b.sex, b.amount, b.wallet, 
                        b.score, b.develop_count, b.country, b.province, b.city, b.role_id,
                        c.school_name, c.school_students, c.school_teachers')
                    ->select();
            }
            $count  = M('t_user_relative a', null)
                ->join('left join t_user b on a.user_id = b.id')
                ->where($where)
                ->count();

            return $list;
        }

        //导入所用用户下级
        $where  = $this->createWhere($keyword, 'a');
        if($timeS){
            $where  .= ' and a.subscribe_time > '.$timeS;
        }
        if($timeE){
            $where  .= ' and a.subscribe_time < '.$timeE;
        }
        if($count !== 'only'){
            $list   = M('t_user a', null)
                ->join('left join t_user_sole_info c on a.id = c.user_id')
                ->where($where)
                ->limit($start, $length)
                ->field('a.id, a.nickname, a.truename, a.mobile, a.sex, a.amount, a.wallet, 
                    a.score, a.develop_count, a.country, a.province, a.city, a.role_id,
                    c.school_name, c.school_students, c.school_teachers, vip_level, vip_endtime')
                ->select();
        }
        $count  = M('t_user a', null)->where($where)->count();
        return $list;

    }
    
    /**
     * 创建where语句
     * @param   $tableName 表名称
     * @param   $keyword 关键词
     * @return  $where 查询语句
     */
    function createWhere($keyword, $tbName = ''){
        if($tbName) $tbName     = $tbName.'.';

        $roleMap    = self::ROLE_MAP;
        if(in_array($keyword, $roleMap)){
            $roleId     = array_flip($roleMap)[$keyword];
            $keyword    = false;
        }

        $where  = '1 = 1';
        if($keyword){
            $where  .= sprintf(' and %snickname like "%%%s%%"', $tbName, $keyword);
        }
        if($roleId){
            $where  .= sprintf(' and %srole_id = %d', $tbName, $roleId);
        }

        return $where;
    }

    /**
     * 导出VIP列表
     * @param   $keyword
     * @param   $start
     * @param   $length
     * @param   $sort
     * @param   $desc
     * @return  list or count
     */
    function outVipExcel($keyword, $start, $length, $sort, $desc){
        $where  = 'vip_level > 0 and vip_endtime > '.time();
        if($keyword){
            $where  .= sprintf(' and (nickname like "%s%" or truename like "%s%"', $keyword, $keyword);
        }

        if(in_array($sort, ['vip_level', 'vip_endtime'])){
            if($desc)   $sort   .= ' desc';
        }else{
            $sort   = 'id';
        }
        //导出数据
        if(isset($length) && isset($start)){
            $list   = M('t_user', null)
                ->where($where)
                ->limit($start, $length)
                ->order($sort)
                ->field('id, nickname, truename, username, vip_level, vip_endtime, subscribe_time')
                ->cache(true)
                ->select();

            return $list;
        }

        //获取导出数量
        $count  = M('t_user', null)
            ->where($where)
            ->cache(true)
            ->count();

        return $count;
    }
}